{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The Extended Stabilizer Simulator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Extended Simulator is a new method for classically simulating quantum circuits available in the latest release of [Qiskit-Aer](https://github.com/qiskit/qiskit-aer). \n",
    "\n",
    "This method is an implementation of the ideas published in the paper _Simulation of quantum circuits by low-rank stabilizer decompositions_ by Bravyi, Browne, Calpin, Campbell, Gosset & Howard, 2018, [**arXiv:1808.00128**](https://arxiv.org/abs/1808.00128).\n",
    "\n",
    "It uses a different representation of a quantum circuit, that gives it some unique capabilities. This notebook will give some examples of what the extended stabilizer method can do.\n",
    "\n",
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:17:32.305227Z",
     "start_time": "2019-08-19T17:17:32.300959Z"
    }
   },
   "outputs": [],
   "source": [
    "from qiskit import QuantumCircuit, transpile\n",
    "from qiskit_aer import AerSimulator\n",
    "from qiskit.visualization import plot_histogram\n",
    "\n",
    "import random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:21:43.756467Z",
     "start_time": "2019-08-19T17:21:43.742436Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<qiskit.circuit.instructionset.InstructionSet at 0x7fbd18a23310>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "circ = QuantumCircuit(40, 40)\n",
    "\n",
    "# Initialize with a Hadamard layer\n",
    "circ.h(range(40))\n",
    "# Apply some random CNOT and T gates\n",
    "qubit_indices = [i for i in range(40)]\n",
    "for i in range(10):\n",
    "    control, target, t = random.sample(qubit_indices, 3)\n",
    "    circ.cx(control, target)\n",
    "    circ.t(t)\n",
    "circ.measure(range(40), range(40))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We've created a random circuit with just 60 gates, that acts on 40 qubits. But, because of the number of qubits, if we wanted to run this with say the statevector simulator then I hope you have access to terabytes of RAM!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:21:58.295935Z",
     "start_time": "2019-08-19T17:21:58.246239Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Simulation failed and returned the following error message:\n",
      "ERROR:  [Experiment 0] Insufficient memory to run circuit \"circuit-2\" using the statevector simulator.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This succeeded?: False\n",
      "Why not? ERROR:  [Experiment 0] Insufficient memory to run circuit \"circuit-2\" using the statevector simulator.\n"
     ]
    }
   ],
   "source": [
    "# Create statevector method simulator\n",
    "statevector_simulator = AerSimulator(method='statevector')\n",
    "\n",
    "# Transpile circuit for backend\n",
    "tcirc = transpile(circ, statevector_simulator)\n",
    "\n",
    "# Try and run circuit\n",
    "statevector_result =  statevector_simulator.run(tcirc, shots=1).result()\n",
    "print('This succeeded?: {}'.format(statevector_result.success))\n",
    "print('Why not? {}'.format(statevector_result.status))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Extended Stabilizer method, in contrast, handles this circuit just fine. (Though it needs a couple of minutes!)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:22:26.158636Z",
     "start_time": "2019-08-19T17:22:22.534910Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This succeeded?: True\n"
     ]
    }
   ],
   "source": [
    "# Create extended stabilizer method simulator\n",
    "extended_stabilizer_simulator = AerSimulator(method='extended_stabilizer')\n",
    "\n",
    "# Transpile circuit for backend\n",
    "tcirc = transpile(circ, extended_stabilizer_simulator)\n",
    "\n",
    "extended_stabilizer_result = extended_stabilizer_simulator.run(tcirc, shots=1).result()\n",
    "print('This succeeded?: {}'.format(extended_stabilizer_result.success))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How does this work?\n",
    "If you're interested in how exactly we can handle such large circuits, then for a detailed explanation you can [read the paper!](https://arxiv.org/abs/1808.00128)\n",
    "\n",
    "For running circuits, however, it's important to just understand the basics.\n",
    "\n",
    "The Extended Stabilizer method is made up of two parts. The first is a method of decomposing quantum circuits into _stabilizer circuits_, a special class of circuit that can be efficiently simulated classically. The second is then a way of combining these circuits to perform measurements.\n",
    "\n",
    "The number of terms you need scales with the number of what we call _non-Clifford Gates_. At the moment, the method knows how to handle the following methods:\n",
    "```python\n",
    "circ.t(qr[qubit])\n",
    "circ.tdg(qr[qubit])\n",
    "circ.ccx(qr[control_1], qr[control_2], qr[target])\n",
    "circ.u1(rotation_angle, qr[qubit])\n",
    "```\n",
    "\n",
    "The simulator is also able to handle circuits of up to 63 qubits.\n",
    "     \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One thing that's important to note is these decompositions are approximate. This means that the results aren't exactly the same as with the State Vector simulator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:23:52.873028Z",
     "start_time": "2019-08-19T17:23:52.863305Z"
    }
   },
   "outputs": [],
   "source": [
    "small_circ = QuantumCircuit(2, 2)\n",
    "small_circ.h(0)\n",
    "small_circ.cx(0, 1)\n",
    "small_circ.t(0)\n",
    "small_circ.measure([0, 1], [0, 1])\n",
    "# This circuit should give 00 or 11 with equal probability...\n",
    "expected_results ={'00': 50, '11': 50}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:23:54.879606Z",
     "start_time": "2019-08-19T17:23:53.249255Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100 shots in 0.4958779811859131s\n"
     ]
    }
   ],
   "source": [
    "tsmall_circ = transpile(small_circ, extended_stabilizer_simulator)\n",
    "result = extended_stabilizer_simulator.run(\n",
    "    tsmall_circ, shots=100).result()\n",
    "counts = result.get_counts(0)\n",
    "print('100 shots in {}s'.format(result.time_taken))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:23:55.222602Z",
     "start_time": "2019-08-19T17:23:55.101958Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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HTtCAFavXt38o48+Or1v376HwHf/2/bt28NKS0sBOHLkiBUVFQXFxsYWh4aGurfeeivqs88+i6p63Ntuuy3hyJEjtmjRoohPP/205fjx4+s8SWhxcTEjR45MHTVq1N7rrrvuJ/tNmjQpb86cObGffvrpaWVlZRw4cCBo/vz5Lfft29cg+avRe+LM7EbgdiAeWAfc6pz71zHaG/A7YBKQAuwF5jjnplZqMwh4EugG5ACPOedmnrCTEBGRU1pd53FrDOPGjetUeZ64884778DChQs3T5gwocPNN9+8s3///gUA99xzz46JEyemZGZmftOrV68jv/zlL/empqb2KC0t5euvv15377337nbO2c9//vMz8/LyQlu1alV86aWX7vvtb3/7Q201PPbYY7lXXnll+w4dOvSIjY0tHj9+/J6XX345DnxXTj744IPvJk+e3C45OfnsoqIiS0lJOfLAAw/sqG3fqlq1alXywQcfnP7II48kFhQUBEVHR5eMHDly74MPPrgL4Morr9z75ptvtoqOju7Zrl27wvXr13/z0EMPfX/llVemFhUV2ZAhQ/YPGTJkf+VjxsTEFEdHR5fEx8ef3bx587LHH398a69evY7U9ee/ZcuWsJUrV0asW7euxZ/+9KeKAJqZmblu4MCBh59//vnsW265pf3WrVubNW/evCw9Pf3QsGHDGmRKGKtulN+JYma/AeYCNwLL/N//C+jqnKt2Qj0zexL4Bb7g9zXQEoh3zi30b08B1gJ/Bl4ABvi/j3POvXusetLT011GRkYDnJmIiJwszGylcy69fDkzMzM7LS1tTyBrklNXZmZm67S0tOTqtjV2T9wUYLZzbpZ/ebKZXQzcANxVtbGZdQYmA2c7576ptGl1pdeTgBzn3GT/8jdm1g+4DThmiBMRERHxqka7J87MwoA+wEdVNn0EnHv0HgBcCmwBLjazLWaWbWZzzKzy9fL+1Rzz70C6mdV7dImIiIiIFzRmT1xrIBioOv/LLuCiGvbpAJwBjAMmAg54HHjPzPo758qAtsA/qjlmiP89cytvMLPrgesBEhISKh6x1KFDByIjI8nMzAR8N7h369aNpUuXAr5r+gMGDGDVqlUcOHAAgPT0dHbt2lUxX1mnTp1o1qwZa9f6BuDExsZy5plnsmzZMgCaNWtG//79ycjI4NChQwD069eP7du3VzxtoHPnzgQHB7N+/XoA2rZtS0pKCsuXLwcgPDycfv36sWLFCgoKfANg+vfvT1ZWFjt3+ga/dO3aldLSUjZs2AD4nlDQrl07VqxYAUBERATp6eksX76cwsJCAAYMGMDGjRsrnlDQvXt3CgsL2bRpEwBJSUnExcVRfvk5KiqK3r17s2zZMkpKSgAYOHAg69atIz8/H4C0tDQOHjzIli1bAEhOTqZVq1asWrUKgOjoaNLS0liyZAnOOcyMQYMGkZmZWfHg+d69e7N3716ys7P1e9LvSb8n/Z4a5fck4hWNdk+cmSUAO4CBlQcymNnvgcudc12q2edl4Dqgs3Nuo3/dmcAG4GfOuRVmthF43Tn3h0r7DQIW47t3rsZhvbonTkREqtI9cdKUHOueuMacYmQPUIqv56yyWI7unSuXC5SUBzi/TUAJUP4okJ01HLMEyD+egkVERICysrIyq72ZSMPy/3dXVtP2RgtxzrkiYCUwtMqmocDnNez2GRBiZqmV1nXAd6l0q395OUdfjh0KZDjn/uNZkEVERPzW5uXltVSQk8ZUVlZmeXl5LfHNwFGtxh6d+iTwupl9gS+gTQISgJkAZjYNOMc5N8Tf/h/AKuDPZnarf93TwAqg/DroTOBmM3saeAk4D9/9c5ef8LMREZGTXklJybU7d+58ZefOnd3RJPnSeMqAtSUlJdfW1KBRQ5xz7k0ziwHuxTfZ71pguHOuvFctHkit1L7MzH4BPAssBQqAj4Ep/kENOOeyzGw48BS+qUpygFtqmyNORESkLvr06bMbGBnoOkSqatTJfpsaDWwQEZGqqg5sEGmq1C0sIiIi4kGN/uxUObVs7nx/oEtoslI33B/oEkRExMPUEyciIiLiQQpxIiIiIh6kECciIiLiQQpxIiIiIh6kECciIiLiQQpxIiIiIh6kECciIiLiQQpxIiIiIh6kECciIiLiQQpxIiIiIh6kECciIiLiQQpxTdxDDz1EWFgYoaGhXHzxxUdtf/rppzEzwsPDCQ8P58ILL6x1382bNxMTE0NYWBgxMTFkZWU1yrmINAX6TInIyUIhrgkrKirigQce4KOPPmLfvn0sWbKEv/3tb0e1i42NpaCggIKCAj799NNa97388svp27cvRUVF9O3bl3HjxjXqeYkEij5TInIyUYhrwmbPnk3Lli0ZPHgwERERDBw4kBkzZhz3vl999RXTp08HYPr06axevfqEnYNIU6LPlIicTBTimrANGzYQExNTsZySkkJubu5R7fLy8ggPD6dNmzYsWLCg1n2Li4vp2bMnAD179qSkpOREnoZIk6HPlIicTBTimjDnXK1txowZQ05ODgUFBdx88838+te/rvO+IqcafaZE5GSiENeEdenShfz8/IrlrKws4uPjf9KmXbt2tG3bFoDf//73lJWVsWHDhmPuGxoayldffQX4LgOFhISc6FMRaRL0mRKRk4lCXBN25ZVXsn//fpYuXcqhQ4dYunQpN95440/arFmzhrKyMgBeffVVADp16nTMfdPS0pg6dSoAU6dOrbgMJHKy02dKRE4m+udiE9a8eXPuvfdeLrroIpxzDB48mEsvvZTx48cD8MYbb/CHP/yB9957DzMjODiYGTNmEBQUVOO+5fv169ePsLAwIiIi+PLLLwN5miKNRp8pETmZ2Kl8n0d6errLyMgIdBkntc2d7w90CU1W6ob7A12CiFTDzFY659IDXYdIbXQ5VURERMSDFOJEREREPEghTkRERMSDFOJEREREPEghTkRERMSDFOJEREREPEghTkRERMSDFOJEREREPEghTkRERMSDFOJEREREPEjPTm0A1z0d6AqarqmBLkA8SZ+pms26NdAViEhToZ44EREREQ9SiBMRERHxIIU4EREREQ9SiBMRERHxIIU4EREREQ9SiBMRERHxIIU4EREREQ9SiBMRERHxIIU4EREREQ9SiBMRERHxIIU4EREREQ9SiBMRERHxIIU4EREREQ9SiBMREQAWLVpE586d6dixI9OnT6+x3ZdffklwcDDvvPMOANu2beOCCy7grLPOolu3bjzzzDMVbffu3cvQoUPp1KkTQ4cOZd++fSf8PEROFQpxIiJCaWkpN910Ex9++CHr169n3rx5rF+/vtp2d955J8OGDatYFxISwhNPPME333zDv//9b2bMmFGx7/Tp0xkyZAibNm1iyJAhxwyHIlI/jR7izOxGM8sysyNmttLMzq/jfp3M7KCZHaqyfrCZuWq+upyYMxAROfl88cUXdOzYkQ4dOhAWFsa4ceNYsGDBUe2ee+45Ro8eTWxsbMW6+Ph4evfuDUBkZCRnnXUWO3bsAGDBggVcddVVAFx11VX89a9/bYSzETk1NGqIM7PfAM8AjwC9gM+BD82sfS37hQHzgaXHaNYN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eK+FQIlzbuSx2qWnp7vyP3bH47qnj/sQJ62pL94f6BKarNQN9we6hCZLn6ma6TNVs4b6TJnZSudceoMcTOQEasyBDXuAUqBtlfWxHN07d7xWAJ0a+JgiIiIiTUajhTjnXBGwEhhaZdNQfKNUG1JPfJdZRURERE5KjT069UngdTP7AvgM38jTBGAmgJlNA85xzg0p38HMuuK71601EGFmPQGcc1/5t98KZAPr/O1+C1wGjG6cUxIRERFpfI0a4pxzb5pZDHAvvrnc1gLDnXNb/U3iOXqUwELgjErLq/3fzf89DHgcSAQK8IW5Ec65hQ1/BiIiIiJNQ2P3xOGcewF4oYZtE6tZl1zL8R4DHmuI2kRERES8Qs9OFREREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD2r0EGdmN5pZlpkdMbOVZnZ+Le17mNkSMyswsx1m9j9mZlXaDPIf64iZbTGzSSf2LEREREQCq1FDnJn9BngGeAToBXwOfGhm7WtoHwV8DOwC+gK3ALcDUyq1SQEW+o/VC5gGPGdmo0/cmYiIiIgEVmP3xE0BZjvnZjnnvnHOTQZygRtqaD8BaAFc5Zxb65x7F3gUmFKpN24SkOOcm+w/5ixgDnDbiT0VERERkcAx51zjvJFZGHAYuNw593al9TOA7s65QdXs8xoQ45wbUWldX+ALoINzLsvMlgJfO+duqtTm18AbQAvnXHGVY14PXO9f7AxsaKhzlGq1BvYEugiRk4g+UyfeGc65NoEuQqQ2IY34Xq2BYHyXRivbBVxUwz5tge3VtC/fluX//o9q2oT43zO38gbn3MvAy/UpXP5zZpbhnEsPdB0iJwt9pkSkXCBGp1bt+rNq1tXWvur6urQREREROWk0ZojbA5Ti6zmrLJaje+fK7ayhPZX2qalNCZD/H1UqIiIi0sQ1WohzzhUBK4GhVTYNxTeytDrLgfPNrHmV9jlAdqU2VS/HDgUyqt4PJwGhS9ciDUufKREBGnFgA1RMMfI6cCPwGb6RpdcA3ZxzW81sGnCOc26Iv31LfAMPFgMPAWcCs4EHnHNP+NukAGuBWcBLwHnAC/gGULzbaCcnIiIi0ogac2ADzrk3zSwGuBeIxxe+hjvntvqbxAOpldrvN7OhwAwgA9gHPAE8WalNlpkNB57CN1VJDnCLApyIiIiczBq1J05EREREGoaenSoiIiLiQQpxIiIiIh6kECciIiLiQY06sEFODWbWFegKtAR+BFY457ICW5WIiMjJRQMbpEGZ2VRgAtAJ2IFvwuUyYDW+59l+Bjin//BERESOi0KcNBj/9DHZwO3OuZlmlgScA/QH+gDNgbucc4sDVqSIh5hZKJACbHXOFQa6HhFpWnRPnDSkXwPfOudmAjjntjnn3nXO3Qbciq9n7m9m1iGQRYp4yE34erFnmtkvzaytmQVXbmBmUWZ2iT/wicgpRCFOGlI+0NrMBgKYWXD5HxznXCbwW2A9cHHgShTxlN8AXwAdgb/ie8zgH81sgP+JNgDjgd/rMYMipx6FOGlIHwBbgf/PzHo450qdc6XlG51zR4ASICZQBYp4hZm1AYqBWc6584EzgD8BvwCWAp+a2Z34erlXBKxQEQkY3RMnDcLMzDnnzOw84DmgB/Ahvj86a4BWwLnAg0Av51x2oGoV8QIziwfGAeudc3+vsq0XcK1/ezSQ5Jzb0fhVikggKcRJgzKzKKAZvoEMVwAj/Ms78fXCPe+ceyZwFYp4h5mF4xvNfcTMrHx9+ehuM3sY3/OnewWqRhEJHM0TJ8fNzGLxBbYpwF7gCJCD7/Lq74HTgfbAZ865XYGqU8RrnHMF5eGt6rQ8ZtYCGA28GojaRCTw1BMnx83MZgPdgPfwhbhWQBrQBV+Yu9s592XAChTxGH+P9sFjzadoZs3xDXyY55wrarTiRKTJUIiT4+LvJTiI75LO0krr2gP98N230wH4tXNudcAKFfEQM3sJ36jUL/DNEXegmjanO+d+aPTiRKTJ0OhUOV5dgSygoifA+Wx1zr2FbyTdD8DYANUn4ilmdjlwHfAEsADflCK/MrNU/z1y5ffKzTGz7gEsVUQCTD1xclz8f0zeB1oAVwKbnXNlVdpMBq5xzvUMQIkinmJms4BS4DFgFHAVkApsABYCnwCdgWecc2GBqlNEAk89cXJcnHMFwD1AOPAacKWZJZnZaVBx8/UgYG3gqhTxBjMLwdez/YNzbotz7nHnXA+gL7AEX6B7C980Pq8HrlIRaQrUEycNwn9Z5z5gJPAjvpnl84CLgFzgWufc14GrUMQbzCwaiHPOfWtmYUBx5QEOZvYbYB7Q2zn3VaDqFJHAU4iTBuWfbmQEcBm+qUbWAm87574NaGEiHmZmQfj+f11qZtfhu5TaItB1iUhgKcTJCWNmQVXvjxOR42NmU4Bg59wfA12LiASWQpyIiIeYWShQqn8giYhCnIiIiIgHaXSqiIiIiAcpxImIiIh4kEKciIiIiAcpxImIiIh4kEKciIiIiAcpxImIiIh40P8Pdb3zIK07LxEAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plot_histogram([expected_results, counts],\n",
    "               legend=['Expected', 'Extended Stabilizer'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can control this approximation error using the `extended_stabilizer_approximation_error` in Qiskit Aer. The default error is 0.05. The smaller the error, the more precise the results, but also the longer your simulation will take and the more memory it will require."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:24:01.638958Z",
     "start_time": "2019-08-19T17:23:57.206364Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100 shots in 1.404871940612793s\n"
     ]
    },
    {
     "data": {
      "image/png": "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HulYs99Zs2Z1ra7tmWee6VC9/KKLLkq54YYbEmurJSkpacBrr70WAxATEzOw+ruMiooaZGZDsrKyIgAWL17cvk+fPn1jYmIGDho0qM/q1auj/Pu44447up500kl927VrN7ipQU4hrhVzzjXY5uKLLyY3N5fi4mKuv/56fvWrXzV6Wy+rbf/M7AfvBw8ezLZt28jMzGTGjBlccMEFjd5Wjk86puqmY+r4M2/evB1fffVV2zlz5sS/++670UuWLOm4aNGi7NjY2MpXXnllc6dOncqqR+9SUlLKHnjggc5vv/32CcuWLcvKy8vLPOGEEyqmTZvW3b/Pjz/+OHrz5s0bly5d+vUf//jHxHXr1kUC3HLLLYk5OTltNm/e/Pl777339ZIlS44EpYqKCsaPH99rwIABh/Ly8jZ88MEHWfPmzevy6quvxja0bU2nnXba99nZ2ZFXXnll8ptvvhmzf//+Iznm4osvPjBjxoxd48eP33fo0KH1WVlZXwB06dKl/M033/ymqKho/Z/+9Kfs//mf/0leuXLlkaBYWFgYvmfPnrDc3NwN8+fPz545c+aJmZmZbZryXRcVFX1W/V1eeeWVu4cMGXIwJSWlbOXKlW2vu+66lKeffnrbvn37PrviiisKLrzwwl7FxcVHDpBXX321w9KlSzfv3bt3fXh4eFM+ViGuNevTpw+FhYVH3mdnZx/5jbZat27d6NrV98vQ3XffTWVlJVlZWfVuGx4ezmeffQb4TgOFhXnv0shu3bqxffv2I+937NhBYuIPf1mKjY0lOjoagHHjxlFWVsaePXvq3bZLly5HRlfy8vLo3LkzcvzQMVU3HVPeNXny5F4xMTEDq3/+8Ic/dASIiYmpfO6557beddddyVdccUWP2bNnb09NTa1zqGfhwoWd7rvvvp2pqallUVFRLiMjI/edd96J8x8deuCBB3Kjo6PdsGHDik8++eTiNWvWRAG88cYbHW677ba8Ll26VPTq1avst7/97ZGLSpcvX95u7969YY8++mheZGSk69u3b+lll11WsHjx4g4NbVtT3759S5cuXZqVl5cXPmXKlJ6dO3ceeNFFF6X4h7maJk2atL9fv34lISEhjB8//uDw4cMP/POf/4z2b/PYY4/lRkVFufHjxx8888wz9y9atKhDXf3VZ8GCBXF///vfO7zxxhtb2rRp45555pmOl112WcFZZ531fVhYGDNmzCgMDw93H330UbvqbaZPn57fq1evsujo6Cb/pqgQ14pNmTKF/fv3s2LFCg4ePMiKFSu49tprf9Bmw4YNVFZWAvDcc88B0Lt373q3TUtLY9asWQDMmjXryGkgLxk6dCibN28mOzub0tJSlixZctTF6bt27ToyQvDpp59SWVlJfHx8vdtOmDCB559/HoDnn3+e888/P7g7Js1Kx1TddEx514svvvhNUVHRZ9U///3f/72net2ZZ555KDk5ucQ5x5VXXrm3vn7y8vIiLr300iOBsH///v1CQ0PZsWPHkeGh7t27H0l0UVFRlQcPHgwFKCgoCE9JSSmtXtejR48jr7du3RpRUFAQ4R8058yZk1BQUBDW0La1Ofvss79funTp1n379mW+//77X61evTrm9ttvT6ir/csvvxyblpbWp3379gNjYmIGLl++vP2ePXuO/KYVExNTHhsbW1n9Pjk5uTQ3N7dpQ2LAxx9/HHXLLbd0f/nll79JTEwsB9ixY0fE/Pnzu/jve35+fviOHTsiqrc78cQTm34xXBXv/br4IxIZGcmdd97JOeecg3OO0aNHc/755zN58mQAXnzxRX7/+9/z5ptvYmaEhoYyd+5cQkJC6ty2ervTTjuNiIgIoqOj+fe//92Su/kfCQsL46mnnmLs2LFUVFRwxRVX0K9fP+bNmwfA9OnTeeWVV3jmmWcICwsjKiqKJUuWYGZ1bgu+f4AnTpzIn//8Z7p3787f/va3ltxNCTAdU3XTMXV8ysjI6FRaWmqdO3cuu+uuu7pmZGTsAjCzo0Z9unTpUjZ//vzsn/3sZ9/XXFd9fVddOnbsWJaTkxORnp5+GCAnJ+dI+5SUlNKkpKSSbdu2bWzqtg0ZNWrUoXHjxu378ssvo2rbr+LiYrv88stTn3766ZzJkyd/16ZNG3fOOeek+l8CUFRUFHbgwIGQ6iC3Y8eOiL59+xY3tgaA3NzcsIkTJ/Z6+OGHvx0+fPiRbZOSkspuuOGGvIceemhXXdvW9nfRWApxrdzdd9/N3Xff/YNlL7744pHX9f0PsbZtwTeqsHdvvb+QecK4ceMYN27cD5ZNnz79yOvrr7+e66+/vtHbAsTHx/Phhx8GtlBpVXRM1U3H1PFlw4YNbTIyMpLee++9rOjo6Mrhw4f/5Be/+MX+008/vTgxMbF8//79YYWFhaHx8fEVAP/1X/+1+8477+yWkpKSfdJJJ5Xm5uaGffTRR9G/+c1vvmvosyZMmLD3oYceShg1atT3Bw4cCPnTn/505Lz56NGjv4+Ojq644447ut522235kZGRbv369ZGHDh0KGTVq1KH6tq3pvffei964cWPkpEmTvktKSipfv3595Pvvv3/CJZdcsgd8178tW7YsoqKigtDQUA4fPmylpaUhnTt3LgsPD3cvv/xy7McffxxbM6TddNNNiXPmzNm5bNmydh999FH7+++/P7ex33NZWRkTJkxIvfDCC/deddVVP5gIcfr06QUTJ07sNXbs2KLRo0d/f/DgwZClS5fGjB07tiguLq6yrj4bSyFORESkiRo7j1swTJo0qbf/PHHDhw8/sHTp0i2XXnppz+uvv37XsGHDigHuuOOOnVOnTu2RmZn55aBBgw7/4he/2JuamjqgoqKCzz//fNOdd9652zlnP/vZz04qKCgI79ChQ9n555+/rzEh7uGHH86bMmVK9549ew7o3Llz2eTJk/fMnz+/C/hGed9+++1vZsyY0S0lJeWU0tJS69Gjx+F77713Z0Pb1tShQ4fyt99++4QHH3wwqbi4OCQuLq58woQJe++77758gClTpux96aWXOsTFxQ3s1q1byRdffPHl/fff/+2UKVNSS0tL7eyzz95/9tln7/fvMz4+viwuLq48ISHhlMjIyMpHH31026BBgw439vvfunVrxNq1a6M3bdrU9s9//vORAJqZmblp5MiRh5566qmcG264ofu2bdvaREZGVqanpx8cO3ZsUWP7r48d73dc1Sc9Pd2tWbOmpcsQEZFWxMzWOufSq99nZmbmpKWl7alvG5HmkpmZ2TEtLS2ltnW6sUFERETEgxTiRERERDxIIU5ERETEgxTiRERERDxIIU5ERKR+lZWVlXqOmARd1X93dU5FohAnIiJSv40FBQXtFeQkmCorK62goKA9UOskyaB54kREROpVXl4+bdeuXc/u2rWrPxr8kOCpBDaWl5dPq6uBQpyIiEg9hgwZshuY0GBDkSDTbxQiIiIiHqQQJyIiIuJBOp0aAFc93tIVtF6znrmnpUtotVKz7mnpElotHVN10zFVNx1T8mOjkTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERDwp6iDOza80s28wOm9laMzujkdv1NrMiMztYY/loM3O1/PRpnj0QERERaXlBDXFmdgnwBPAgMAj4BHjHzLo3sF0EsARYUU+zfkCC38/mQNQsIiIi0hoFeyRuJrDQObfAOfelc24GkAdc08B2DwEbgL/V02a3c26X309FgGoWERERaXWCFuKqRtOGAO/XWPU+cHo9240Hfg7c0MBHrDGzPDP70MzOPKZiRURERFq5sCB+VkcgFMivsTwfOKe2DcwsAVgAXOicKzKz2ppVj+T9G4gALgM+NLPRzrmjTr+a2dXA1QCJiYksW7YMgJ49exITE0NmZiYA8fHx9OvXjxUrfF2EhYUxYsQI1q1bx4EDBwBIT08nPz8fSG3sdyByxO7du6moqCArKwuApKQkunXrxurVqwGIjo4mPT2dVatWUVJSAsCIESP4+uuv2b17NwD9+/enpKSEzZt9Vw8kJyfTpUsX1qxZA0BsbCyDBw9m5cqVlJeXAzBy5Eg2bdpEYWEhAGlpaRQVFbF161YAUlJS6NChA+vWrQMgLi6OtLQ0li9fjnMOM2PUqFFkZmayb98+AAYPHszevXvJyckBju142r59OzA68F+4HPfy8vICcjyJeIU554LzQWaJwE5gpHPuX37L7wZ+7Zw76kYEM/sQWOac+33V+6nAU8656AY+aylQ7pybUF+79PR0V/2P3bG46vFj7uK4NeuZe1q6hFYrNeueli6h1dIxVTcdU3UL1DFlZmudc+kB6UykGQXzmrg9QAXQtcbyzhw9OlftLOBuMys3s3Lgz0C7qvdX1/NZq4Hex1qwiIiISGsVtNOpzrlSM1sLjOGHNyiMAV6tY7MBNd6fD9wBnIpvVK8uA/GdZhURERE5LgXzmjiAx4C/mtmnwMfAdCARmAdgZhnAqc65swGccxv9NzazdKDSf7mZ3QjkAJvwXRP3G+AC4KLm3hkRERGRlhLUEOece8nM4oE78c3lthEY55zbVtUkgabfJRABPAokAcX4wtx459zSwFQtIiIi0voEeyQO59zTwNN1rJvawLYLgYU1lj0MPByY6kRERES8Qc9OFREREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD1KIExEREfEghTgRERERD2pSiDOzEDML8Xvf1cymmdnwwJcmIiIiInVp6kjc28AMADOLBtYAjwDLzGxKgGsTERERkTo0NcQNAT6qen0hcADoDFwF3BTAukRERESkHk0NcTHAd1Wvfwb83TlXhi/YpQayMBERERGpW1ND3LfAcDNrB4wFPqha3gE4FMjCRERERKRuYU1s/xjwV+AgsA1YUbV8JPB5AOsSERERkXo0KcQ55/5kZmuBZOAD51xl1aotwF2BLk5EREREatfUkTicc2vw3ZXqv+ztgFUkIiIiIg1q8mS/ZnatmW0ys0Nm1rNq2a1mNjHw5YmIiIhIbZo62e+NwJ3AfMD8VuUC1wewLhERERGpR1NH4qYDVznnngDK/ZavA/oFrCoRERERqVdTQ9yJwMZalpcBUcdejoiIiIg0RlND3FZgcC3LxwFfHHs5IiIiItIYTb079VHgKTNri++auGFmdhlwC3BFoIsTERERkdo1dZ6458wsDHgQaItv4t+dwA3OuZeaoT4RERERqcV/Mk/cAmCBmXUEQpxzuwNfloiIiIjUp8khrppzbk8gCxERERGRxmswxJnZBmCUc26fmX0OuLraOudOCWRxIiIiIlK7xozEvQqU+L2uM8SJiIiISHA0GOKcc/f6vb6nWasRERERkUZp6mO3PjKzE2pZHmtmHwWuLBERERGpT1Mn+x0NRNSyPBI445irEREREZFGadTdqWbm/5SGU8xsr9/7UGAsvvniRERERCQIGjvFyBp8NzQ44P1a1hcDMwJVlIiIiIjUr7Ehrge+x2xtBU4FCvzWlQK7nXMVAa5NREREROrQqBDnnNtW9bKp19CJiIiISDNozGS/FwJvOufKql7XyTn3/wWsMhERERGpU2NG4l4BugK7q17XxeG7yUFEREREmlljJvsNqe21iIiIiLQchTIRERERD2rsNXGNomviRERERIKjsdfENYauiRMREREJkiZdEyciIiIirYMCmoiIiIgHaZ44EREREQ8K+jxxZnYtcDOQAGwC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\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Add runtime options for extended stabilizer simulator\n",
    "opts = {'extended_stabilizer_approximation_error': 0.03}\n",
    "\n",
    "reduced_error = extended_stabilizer_simulator.run(\n",
    "    tsmall_circ, shots=100, **opts).result()\n",
    "\n",
    "reduced_error_counts = reduced_error.get_counts(0)\n",
    "print('100 shots in {}s'.format(reduced_error.time_taken))\n",
    "plot_histogram([expected_results, reduced_error_counts],\n",
    "               legend=['Expected', 'Extended Stabilizer'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simulator Options"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are several other options you can tweak to control how the extended stabilizer method performs. What these options are and their explanation can all be found in the Qiskit Aer documentation. However, I want to highlight two important ones that can help to optimize your simulations.\n",
    "\n",
    "To perform measurements, the extended stabilizer method uses a Markov chain method to sample outcomes at random. This Markov chain has to be run for some time we call the 'mixing time' before it will start sampling, and has to be re-mixed for every circuit shot.\n",
    "\n",
    "If you expect your circuit output to be concentrated on just a few output states, then you can likely optimize your simulations by reducing the `extended_stabilizer_mixing_time` option.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:24:03.270544Z",
     "start_time": "2019-08-19T17:24:03.132881Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The circuit above, with 100 shots at precision 0.03 and default mixing time, needed 1s\n",
      "Dialing down the mixing time, we completed in just 1.4710919857025146s\n"
     ]
    }
   ],
   "source": [
    "print(\"The circuit above, with 100 shots at precision 0.03 \"\n",
    "      \"and default mixing time, needed {}s\".format(int(reduced_error.time_taken)))\n",
    "\n",
    "opts = {\n",
    "    'extended_stabilizer_approximation_error': 0.03,\n",
    "    'extended_stabilizer_mixing_time': 100\n",
    "}\n",
    "\n",
    "optimized = extended_stabilizer_simulator.run(\n",
    "    tsmall_circ, shots=100, **opts).result()\n",
    "\n",
    "print('Dialing down the mixing time, we completed in just {}s'.format(optimized.time_taken))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly, if your circuit has some non-zero probability on all amplitudes (e.g. if it's a random circuit), then you can avoid this expensive re-mixing step to take multiple shots from the output at once. This can be enabled by setting `extended_stabilizer_measure_sampling=True`.\n",
    "\n",
    "For example, let's look again at the random circuit from the start of the tutorial, running for 100 shots:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:24:20.656799Z",
     "start_time": "2019-08-19T17:24:04.332417Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100 shots took 29.634929895401 s\n"
     ]
    }
   ],
   "source": [
    "# We set these options here only to make the example run more quickly.\n",
    "opts = {'extended_stabilizer_mixing_time': 100}\n",
    "\n",
    "multishot = extended_stabilizer_simulator.run(\n",
    "    tcirc, shots=100, **opts).result()\n",
    "print(\"100 shots took {} s\".format(multishot.time_taken))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:24:21.070233Z",
     "start_time": "2019-08-19T17:24:20.918300Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "With the optimization, 100 shots took 0.4958779811859131 s\n"
     ]
    }
   ],
   "source": [
    "opts = {\n",
    "    'extended_stabilizer_measure_sampling': True,\n",
    "    'extended_stabilizer_mixing_time': 100\n",
    "}\n",
    "\n",
    "measure_sampling = extended_stabilizer_simulator.run(\n",
    "    circ, shots=100, **opts).result()\n",
    "print(\"With the optimization, 100 shots took {} s\".format(result.time_taken))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## When shall I use it?\n",
    "\n",
    "If you have smaller circuits with lots of non-Clifford gates, then the statevector method will likely perform better than the extended stabilizer. If however you want to look at circuits on many qubits, without needing access to high performance computation, then give this method a try!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-19T17:24:45.930560Z",
     "start_time": "2019-08-19T17:24:45.920568Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<h3>Version Information</h3><table><tr><th>Qiskit Software</th><th>Version</th></tr><tr><td>Qiskit</td><td>0.25.0</td></tr><tr><td>Terra</td><td>0.17.0</td></tr><tr><td>Aer</td><td>0.8.0</td></tr><tr><td>Ignis</td><td>0.6.0</td></tr><tr><td>Aqua</td><td>0.9.0</td></tr><tr><td>IBM Q Provider</td><td>0.12.2</td></tr><tr><th>System information</th></tr><tr><td>Python</td><td>3.7.7 (default, May  6 2020, 04:59:01) \n",
       "[Clang 4.0.1 (tags/RELEASE_401/final)]</td></tr><tr><td>OS</td><td>Darwin</td></tr><tr><td>CPUs</td><td>6</td></tr><tr><td>Memory (Gb)</td><td>32.0</td></tr><tr><td colspan='2'>Fri Apr 02 12:28:14 2021 EDT</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style='width: 100%; background-color:#d5d9e0;padding-left: 10px; padding-bottom: 10px; padding-right: 10px; padding-top: 5px'><h3>This code is a part of Qiskit</h3><p>&copy; Copyright IBM 2017, 2021.</p><p>This code is licensed under the Apache License, Version 2.0. You may<br>obtain a copy of this license in the LICENSE.txt file in the root directory<br> of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.<p>Any modifications or derivative works of this code must retain this<br>copyright notice, and modified files need to carry a notice indicating<br>that they have been altered from the originals.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import qiskit\n",
    "qiskit.__version__\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
